import pandas as pd
import numpy as np
from input import input_data
from matplotlib import pyplot as plt

def box_outliers(data):
    '''
    箱型图检测异常值
    :param data: pandas.series对象。待检测的一维光谱数据
    :return: pandas.series对象。修改后的一维数组
    '''
    # 对待检测的数据集进行排序
    sorted_data = data.sort_values()
    # 判断数据的总数量是奇数还是偶数
    if sorted_data.count() % 2 == 0:
        # 计算Q3，Q1,IQR
        Q3 = sorted_data[int(len(sorted_data) / 2):].median()
        Q1 = sorted_data[:int(len(sorted_data) / 2)].median()
    else:
        Q3 = sorted_data[int(len(sorted_data) / 2 - 1):].median()
        Q1 = sorted_data[:int(len(sorted_data) / 2 - 1)].median()
    IQR = round(Q3 - Q1, 1)
    # 获取1.5倍IQR的值
    upper_bound = round(Q3 + 1.5 * IQR, 1)
    lower_bound = round(Q1 - 1.5 * IQR, 1)
    # 判断哪些值是异常值
    rule = (data > upper_bound) | (data < lower_bound)
    # 获取异常值及其索引
    outliers = data[rule]
    # 如果检测到异常值，用相邻的非异常值替换
    if len(outliers) > 0:
        data[rule] = data.shift(-1)[rule]
        data[rule] = data[rule].fillna(data.iloc[-1])
    return data


def replace_outliers_with_next(matrix):
    '''
    剔除异常数据，并把它替换为右边一个元素数值（如果已经是最右边的元素，则替换为左边一个）
    :param matrix:np.ndarray nxm的光谱数据，n为数据个数，m为每个数据的光谱点数量
    :return:np.ndarray 剔除错误点并修改好了的光谱数据 nxm的光谱数据，n为数据个数，m为每个数据的光谱点数量
    '''
    # 将矩阵转换为DataFrame，以便于处理每一行
    df = pd.DataFrame(matrix)
    # 遍历每一行
    for i in range(df.shape[0]):
        # 应用box_outliers函数检测异常值
        box_outliers(df.iloc[i])
        # 获取右侧的数据，如果右侧没有数据，则使用最后一列的数据
        right_data = df.iloc[i].shift(-1)
        right_data = right_data.fillna(df.iloc[i].iloc[-1])  # 如果最后一列是NaN，则替换为最后一列的数据
        #print(f"右边的元素为：{right_data}")
        # 用右侧数据替换异常值
        df.iloc[i] = df.iloc[i].where(~df.iloc[i].isna(), right_data)
        #df.iloc[i].where(df.iloc[i].isin(outliers), right_data, inplace=True)

    return df.values

if __name__ == "__main__":
    data,_ = input_data()
    n = data.shape[1]
    x = np.linspace(1, n, n)
    plt.plot(x, data[0], label='Original Data', color='blue')
    cleaned_matrix = replace_outliers_with_next(data)
    plt.plot(x, cleaned_matrix[0], label='Cleaned Data', color='red')
    plt.show()

    # matrix = np.array([[1, 2, 3, 4, 5],
    #                    [6, 7, 8, 9, 10],
    #                    [11, 12, 99, 14, 15],
    #                    [16, 17, 18, 19, 20]])
    # cleaned_matrix = replace_outliers_with_next(matrix)
    # print(cleaned_matrix)